﻿///////////////////////////////////////////////////////////////////////////////////////////////
// System.Text.Parsing - © 2012 Sebastien Pellizzari
// Released under the MIT License (http://www.opensource.org/licenses/mit-license.php)
///////////////////////////////////////////////////////////////////////////////////////////////

namespace System.Text.Parsing
{
    /// <summary>Represents a set of options for a parser.</summary>
    [Flags]
    public enum ParserOptions
    {
        /// <summary>Represents no options.</summary>
        None = 0,
        /// <summary>When the EOF token is encountered, the parser will abruptly stop in its current state. This option is useful
        /// for code completion implementers wanting to know in which state the parser is at a given point.</summary>
        StopAtEOF = 1,
    }

    /// <summary>Represents the result of a parsing operation.</summary>
    public enum ParserResult
    {
        /// <summary>The parsing operation has not completed yet.</summary>
        Continue,
        /// <summary>The parsing operation completed successfully.</summary>
        CompletedSuccess,
        /// <summary>The parsing operation encountered an error.</summary>
        CompletedError,
        /// <summary>The parsing operation stopped when it encountered the EOF token.</summary>
        StoppedAtEOF,
    }

    /// <summary>Represents the signature of a method called by a parser when an error is generated.</summary>
    public delegate void ParserErrorHandler<TRange>(TRange errorRange);

    /// <summary>Represents the base class for a parser.</summary>
    /// <typeparam name="TRange">The type of symbol range.</typeparam>
    /// <typeparam name="TTokenValue">The type of token value.</typeparam>
    /// <typeparam name="TSymbolValue">The type of symbol value.</typeparam>
    /// <typeparam name="TTokenizer">The type of tokenizer.</typeparam>
    public abstract class Parser<TRange, TTokenValue, TSymbolValue, TTokenizer>
        where TRange : IDataRange<TRange>
        where TTokenizer : ITokenizer<TRange, TTokenValue>
    {
        /// <summary>Parses tokens from specified tokenizer using specified table until an EOF token is encountered.</summary>
        /// <param name="tokenizer">The tokenizer to use.</param>
        /// <param name="options">A set of parsing options.</param>
        /// <returns>A member of the <see cref="ParserResult"/> enumeration.</returns>
        public ParserResult Parse(TTokenizer tokenizer, ParserOptions options)
        {
            Initialize(tokenizer, options);
            for (; ; )
            {
                var result = Step();
                if (result != ParserResult.Continue) return result;
            }
        }

        /// <summary>When overriden in a derived class, initializes the parser.</summary>
        /// <param name="tokenizer">The tokenizer to use.</param>
        /// <param name="options">A set of parsing options.</param>
        public abstract void Initialize(TTokenizer tokenizer, ParserOptions options);

        /// <summary>When overriden in a derived class, performs a parsing step.</summary>
        /// <returns>The current status of the parsing operation.</returns>
        public abstract ParserResult Step();
    }
}
